﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Xml;
using System.Collections.ObjectModel;
using System.Net;
using System.IO;
using System.Xml.Linq;

namespace ScrumMonster
{
    public sealed class FogBugzContext:IContext
    {
        private string _token = string.Empty;
        private FogBugzContext _currentContext;
        private string _instanceUrl;
        private string _apiUrl;
        private bool _logged = false;
        
        public FogBugzContext Current
        {
            get
            {
                return _currentContext;
            }
        }

        public string ApiUrl
        {
            get
            {
                return this._apiUrl;
            }
        }

        public bool Logged
        {
            get
            {
                return _logged;
            }
        }

        public string Token
        {
            get
            {
                return _token;
            }
        }
        
        public FogBugzContext(string instanceUrl, string username, string password)
        {
            this._instanceUrl = instanceUrl;

            Init();
            _logged = Login(username, password);
            if (!_logged)
                return;
                
        }

        public ReadOnlyCollection<Task> GetTasks(params string[] uniqueIdentifiers)
        {
            string numbers = string.Empty;

            if (uniqueIdentifiers == null || uniqueIdentifiers.Count() == 0)
                return new List<Task>().AsReadOnly();

            foreach (string identifier in uniqueIdentifiers)
                numbers += identifier.ToString() + ",";
    
            string url = string.Format(Urls.ListCases, this._apiUrl, numbers.Substring(0,numbers.Length - 1), this._token);
            
            return GetTaskList(url);
        }

        public ReadOnlyCollection<Task> GetTasks(string projectName, string fixFor)
        {
            string url = string.Format(Urls.ListCasesByProjectFixFor, this._apiUrl, projectName, fixFor, this._token);

            XDocument xmlDoc = XDocument.Load(InvokeFogBugzService(url));

            var cases = from x in xmlDoc.Root.Elements("cases").Elements()
                        select new { caseNumber = x.Attribute("ixBug").Value };

            List<string> list = new List<string>();

            cases.ToList().ForEach(op => list.Add(op.caseNumber));

            return GetTasks(list.ToArray());
        }

        private ReadOnlyCollection<Task> GetTaskList(string url)
        {
            XDocument xmlDoc = XDocument.Load(InvokeFogBugzService(url));

            //sProject,sTitle,sStatus,sPersonAssignedTo,sEmailAssignedTo,hrsCurrEst,hrsElapsed,dtResolved
            ReadOnlyCollection<Task> _list = new List<Task>(
                                            from c in xmlDoc.Root.Elements().First().Elements()
                                            select new Task()
                                            {
                                                Number = (string)(c.Elements("ixBug").First().Value),
                                                //Project             = (string)(c.Elements("sProject").First().Value),
                                                Title = (string)(c.Elements("sTitle").First().Value),
                                                Status = (string)(c.Elements("sStatus").First().Value),
                                                //PersonAssignedTo    = (string)(c.Elements("sPersonAssignedTo").First().Value),
                                                EmailAssignedTo = (string)(c.Elements("sEmailAssignedTo").First().Value),
                                                EstimatedTime = new TimeSpan((int)(double.Parse(c.Elements("hrsCurrEst").First().Value)), 0, 0),
                                                ElapsedTime = new TimeSpan((int)(double.Parse(c.Elements("hrsElapsed").First().Value)), 0, 0),
                                                //Resolved            = (string)(c.Elements("dtResolved").First().Value)
                                            }
                                            ).AsReadOnly();
            return _list;
            
            
        }

        /// <summary>
        /// Load the API version and location
        /// </summary>
        private void Init()
        {
            XDocument xmlDoc = XDocument.Load(InvokeFogBugzService(string.Format("{0}{1}", this._instanceUrl, "/api.xml")));
            var element = from c in xmlDoc.Root.Elements()
                          where c.Name == "url"
                          select c;

            if (element.Count() > 0)
                this._apiUrl = string.Format("{0}/{1}", _instanceUrl, element.First().Value);
        }

        /// <summary>
        /// Login to the FogBugz
        /// </summary>
        /// <param name="username">The registered username/email</param>
        /// <param name="password">The user password</param>
        /// <returns>true if logged in successfully</returns>
        private bool Login(string username, string password)
        {
            XDocument xmlDoc = XDocument.Load(InvokeFogBugzService(string.Format(Urls.Login, this._apiUrl, username, password)));
                        
            var element = from c in xmlDoc.Root.Elements()
                          where c.Name == "error"
                          select c;

            if (element.Count() > 0)
                return false;

            this._token = new XElement("test", from c in xmlDoc.Root.Elements()
                                               where c.Name == "token"
                                               select c).Elements().First().Value;

            return true;
        }

        /// <summary>
        /// Invoke the FogBugz Service
        /// </summary>
        /// <param name="url">The URL to be invoked.</param>
        /// <returns>The XML reader for the response. </returns>
        private static XmlReader InvokeFogBugzService(string url)
        {
            WebRequest request = HttpWebRequest.Create(url);
            
            return XmlReader.Create(request.GetResponse().GetResponseStream());                     
        }        
    }

        


}
